//-----------------------------------------------------------------------------
//  Copyright (c) 2013 by HangZhou HenqgQiao Design Corporation. All rights reserved.
//
//  Project  : 
//  Module   : over sample the input data with 8-phases 311M clock
//  Parent   : 
//  Children : 
//
//  Description: 
//
//  Parameters:
//  Local Parameters:
//
//  Notes       : 
//
//  Multicycle and False Paths

module SOH4_OBSIA(
   input                         SOH4_RESET,
   input                         SOH4_TCLK,

   input                         OBSI_CLK,
   input                         OBSI_IN_FP,
   input                         OBSI_IN_DEN,
   input[7:0]                    OBSI_IN_DATA,

   input                         MPI_CLK,
   input                         MPI_OBSIA_WE,
   input[8:0]                    MPI_OBSIA_WD,
   input[6:0]                    MPI_OBSIA_ADDR,
   output[8:0]                   MPI_OBSIA_RD,

   input[1:0]                    OBSIA_IN_FMCNT4,
   input[8:0]                    OBSIA_IN_FMCNT270,
   input[3:0]                    OBSIA_IN_FMCNT9,
   input[7:0]                    OBSIA_IN_DATA,

   output reg[1:0]               OBSIA_OUT_FMCNT4,
   output reg[8:0]               OBSIA_OUT_FMCNT270,
   output reg[3:0]               OBSIA_OUT_FMCNT9,
   output reg[7:0]               OBSIA_OUT_DATA
   );


wire                             OBWR_FP;
wire                             OBWR_DEN;
wire[7:0]                        OBWR_DATA;
reg[4:0]                         OBWR_CNT32;
reg[2:0]                         OBWR_SECTOR;
wire[2:0]                        OBWR_FIFO_RD_SECTOR;

wire[2:0]                        GRAY8_IN;
reg[2:0]                         GRAY8_SOURCE;
reg[2:0]                         GRAY8_DESTINATION;
reg[2:0]                         GRAY8_OUT;

wire                             DTRM_CLKA, DTRM_CLKB;
wire                             DTRM_WEA;
wire[9:0]                        DTRM_ADDRA, DTRM_ADDRB;
wire[7:0]                        DTRM_DINA, DTRM_DOUTB;


wire[1:0]                        FRMIN_FMCNT4;
wire[8:0]                        FRMIN_FMCNT270;
wire[3:0]                        FRMIN_FMCNT9;
wire[7:0]                        FRMIN_DATA;
reg[2:0]                         FRMIN_SECTOR;
reg[6:0]                         FRMIN_CF_CNT81;


reg[1:0]                         CFRD_RL1_FMCNT4, CFRD_RL2_FMCNT4;
reg[8:0]                         CFRD_RL1_FMCNT270, CFRD_RL2_FMCNT270;
reg[3:0]                         CFRD_RL1_FMCNT9, CFRD_RL2_FMCNT9;
reg[7:0]                         CFRD_RL1_DATA, CFRD_RL2_DATA;
reg[2:0]                         CFRD_RL1_SECTOR, CFRD_RL2_SECTOR;

wire                             CFRM_CLKA, CFRM_CLKB;
wire                             CFRM_WEA;
wire[9:0]                        CFRM_ADDRA, CFRM_ADDRB;
wire[8:0]                        CFRM_DINA, CFRM_DOUTA;
wire[8:0]                        CFRM_DOUTB;

wire[1:0]                        CFRD_OUT_FMCNT4;
wire[8:0]                        CFRD_OUT_FMCNT270;
wire[3:0]                        CFRD_OUT_FMCNT9;
wire[7:0]                        CFRD_OUT_DATA;
wire[2:0]                        CFRD_OUT_SECTOR;
wire[7:0]                        CFRD_OUT_CF;
wire                             CFRD_OUT_OBSI_EN;

reg[1:0]                         DTRD_RL1_FMCNT4, DTRD_RL2_FMCNT4;
reg[8:0]                         DTRD_RL1_FMCNT270, DTRD_RL2_FMCNT270;
reg[3:0]                         DTRD_RL1_FMCNT9, DTRD_RL2_FMCNT9;
reg[7:0]                         DTRD_RL1_DATA, DTRD_RL2_DATA;
reg                              DTRD_RL1_OBSI_EN, DTRD_RL2_OBSI_EN;
reg[7:0]                         DTRD_RL1_CF, DTRD_RL2_CF;

wire[1:0]                        DTRD_OUT_FMCNT4;
wire[8:0]                        DTRD_OUT_FMCNT270;
wire[3:0]                        DTRD_OUT_FMCNT9;
wire[7:0]                        DTRD_OUT_DATA;
wire[7:0]                        DTRD_OUT_OBSI;
wire                             DTRD_OUT_OBSI_EN;
wire[7:0]                        DTRD_OUT_CF;

// ++++++++++++++++++ the overhead data b ++++++++++++++++++ //

   assign OBWR_FP           = OBSI_IN_FP;
   assign OBWR_DEN          = OBSI_IN_DEN;
   assign OBWR_DATA[7:0]    = OBSI_IN_DATA;

always @( posedge SOH4_RESET or posedge OBSI_CLK ) begin
   if ( SOH4_RESET==1'b1 )
      OBWR_CNT32[4:0]                               <= 5'd0;
   else begin
      if ( OBWR_FP==1'b1 && OBWR_DEN==1'b1 )
         OBWR_CNT32[4:0]                            <= 5'd1;
      else if ( OBWR_DEN==1'b1 )
         OBWR_CNT32[4:0]                            <= OBWR_CNT32[4:0] +5'd1;
   end
end

always @( posedge SOH4_RESET or posedge OBSI_CLK ) begin
   if ( SOH4_RESET==1'b1 )
      OBWR_SECTOR[2:0]                              <= 3'd0;
   else begin
      if ( OBWR_FIFO_RD_SECTOR[2:0]==OBWR_SECTOR[2:0] )
         OBWR_SECTOR[2:0]                           <= OBWR_SECTOR[2:0] +3'd4;
      else if ( OBWR_DEN==1'b1 && OBWR_CNT32[4:0]==5'd31 )
         OBWR_SECTOR[2:0]                           <= OBWR_SECTOR[2:0] +3'd1;
   end
end




// ++++++++++++++++++ DATA RAM read address gray convert   ++++++++++++++++++ //
  assign GRAY8_IN[2:0]         =  FRMIN_SECTOR[2:0];

always @( posedge SOH4_TCLK or posedge SOH4_RESET ) begin
   if ( SOH4_RESET==1'b1 )
      GRAY8_SOURCE[2:0]                              <= 3'd0;
   else begin
      case ( GRAY8_IN[2:0] )
      3'b000:  GRAY8_SOURCE[2:0]                     <= 3'b000;
      3'b001:  GRAY8_SOURCE[2:0]                     <= 3'b001;
      3'b010:  GRAY8_SOURCE[2:0]                     <= 3'b011;
      3'b011:  GRAY8_SOURCE[2:0]                     <= 3'b010;
      3'b100:  GRAY8_SOURCE[2:0]                     <= 3'b110;
      3'b101:  GRAY8_SOURCE[2:0]                     <= 3'b111;
      3'b110:  GRAY8_SOURCE[2:0]                     <= 3'b101;
      3'b111:  GRAY8_SOURCE[2:0]                     <= 3'b100;
      default : ;
      endcase
   end
end
always @( posedge OBSI_CLK or posedge SOH4_RESET ) begin
   if ( SOH4_RESET==1'b1 )
      GRAY8_DESTINATION[2:0]                         <= 3'd0;
   else
      GRAY8_DESTINATION[2:0]                         <=GRAY8_SOURCE[2:0];
end
always @( posedge OBSI_CLK or posedge SOH4_RESET ) begin
   if ( SOH4_RESET==1'b1 )
      GRAY8_OUT[2:0]                                 <= 3'd0;
   else begin
      case ( GRAY8_DESTINATION[2:0] )
      3'b000: GRAY8_OUT[2:0]                         <= 3'b000;
      3'b001: GRAY8_OUT[2:0]                         <= 3'b001;
      3'b011: GRAY8_OUT[2:0]                         <= 3'b010;
      3'b010: GRAY8_OUT[2:0]                         <= 3'b011;
      3'b110: GRAY8_OUT[2:0]                         <= 3'b100;
      3'b111: GRAY8_OUT[2:0]                         <= 3'b101;
      3'b101: GRAY8_OUT[2:0]                         <= 3'b110;
      3'b100: GRAY8_OUT[2:0]                         <= 3'b111;
      default : ;
      endcase
   end
end
  assign OBWR_FIFO_RD_SECTOR[2:0]    = GRAY8_OUT[2:0];





  assign DTRM_CLKA         = OBSI_CLK;
  assign DTRM_WEA          = OBWR_DEN;
  assign DTRM_ADDRA[9:0]   = { 2'd0, OBWR_SECTOR[2:0], OBWR_CNT32[4:0] };
  assign DTRM_DINA[7:0]    = OBWR_DATA[7:0];

  assign DTRM_CLKB         = SOH4_TCLK;
  assign DTRM_ADDRB[9:0]   = { 2'd0, CFRD_OUT_SECTOR[2:0], CFRD_OUT_CF[4:0] };
SOH4_OBSIA_DTRM                   INST_OBSIA_DTRM(
   .CLKA                          ( DTRM_CLKA ),
   .WEA                           ( DTRM_WEA ),
   .ADDRA                         ( DTRM_ADDRA[9:0] ),
   .DINA                          ( DTRM_DINA[7:0] ),

   .CLKB                          ( DTRM_CLKB ),
   .ADDRB                         ( DTRM_ADDRB[9:0] ),
   .DOUTB                         ( DTRM_DOUTB[7:0] )
   );




  assign FRMIN_FMCNT4[1:0]         = OBSIA_IN_FMCNT4[1:0];
  assign FRMIN_FMCNT270[8:0]       = OBSIA_IN_FMCNT270[8:0];
  assign FRMIN_FMCNT9[3:0]         = OBSIA_IN_FMCNT9[3:0];
  assign FRMIN_DATA[7:0]           = OBSIA_IN_DATA[7:0];


always @( posedge SOH4_RESET or posedge SOH4_TCLK ) begin
   if ( SOH4_RESET==1'b1 )
      FRMIN_SECTOR[2:0]                             <= 3'd0;
   else begin
      if ( FRMIN_FMCNT4[1:0]==2'd3 && FRMIN_FMCNT270[8:0]==9'd269 && FRMIN_FMCNT9[3:0]==4'd8 )
         FRMIN_SECTOR[2:0]                          <= FRMIN_SECTOR[2:0] +3'd1;
   end
end

always @( posedge SOH4_RESET or posedge SOH4_TCLK ) begin
   if ( SOH4_RESET==1'b1 )
      FRMIN_CF_CNT81[6:0]                           <= 7'd0;
   else begin
      if ( FRMIN_FMCNT4[1:0]==2'd3 && FRMIN_FMCNT270[8:0]==9'd269 && FRMIN_FMCNT9[3:0]==4'd8 )
         FRMIN_CF_CNT81[6:0]                        <= 7'd0;
      else if ( FRMIN_FMCNT4[1:0]==2'd3 && FRMIN_FMCNT270[8:0]<9'd9 )
         FRMIN_CF_CNT81[6:0]                        <= FRMIN_CF_CNT81[6:0] +7'd1;
   end
end

always @( posedge SOH4_RESET or posedge SOH4_TCLK ) begin
   if ( SOH4_RESET==1'b1 ) begin
      CFRD_RL1_FMCNT4[1:0]                          <= 2'd0;
      CFRD_RL2_FMCNT4[1:0]                          <= 2'd0;
      CFRD_RL1_FMCNT270[8:0]                        <= 8'd0;
      CFRD_RL2_FMCNT270[8:0]                        <= 8'd0;
      CFRD_RL1_FMCNT9[3:0]                          <= 4'd0;
      CFRD_RL2_FMCNT9[3:0]                          <= 4'd0;
      CFRD_RL1_DATA[7:0]                            <= 4'd0;
      CFRD_RL2_DATA[7:0]                            <= 4'd0;
      CFRD_RL1_SECTOR[2:0]                          <= 3'd0;
      CFRD_RL2_SECTOR[2:0]                          <= 3'd0;
   end
   else begin
      CFRD_RL1_FMCNT4[1:0]                          <= FRMIN_FMCNT4[1:0];
      CFRD_RL2_FMCNT4[1:0]                          <= CFRD_RL1_FMCNT4[1:0];
      CFRD_RL1_FMCNT270[8:0]                        <= FRMIN_FMCNT270[8:0];
      CFRD_RL2_FMCNT270[8:0]                        <= CFRD_RL1_FMCNT270[8:0];
      CFRD_RL1_FMCNT9[3:0]                          <= FRMIN_FMCNT9[3:0];
      CFRD_RL2_FMCNT9[3:0]                          <= CFRD_RL1_FMCNT9[3:0];
      CFRD_RL1_DATA[7:0]                            <= FRMIN_DATA[7:0];
      CFRD_RL2_DATA[7:0]                            <= CFRD_RL1_DATA[7:0];
      CFRD_RL1_SECTOR[2:0]                          <= FRMIN_SECTOR[2:0];
      CFRD_RL2_SECTOR[2:0]                          <= CFRD_RL1_SECTOR[2:0];
   end
end


// ++++++++++++++++++            MPI configuration  RAM control          ++++++++++++++++++ //
  assign  CFRM_CLKA        = MPI_CLK;
  assign  CFRM_WEA         = MPI_OBSIA_WE;
  assign  CFRM_DINA[8:0]   = MPI_OBSIA_WD[8:0];
  assign  CFRM_ADDRA[9:0]  = {3'd0, MPI_OBSIA_ADDR[6:0]};
  assign  MPI_OBSIA_RD[8:0]= CFRM_DOUTA[8:0];

  assign  CFRM_CLKB        = SOH4_TCLK;
  assign  CFRM_ADDRB[9:0]  = {3'd0, FRMIN_CF_CNT81[6:0] };

SOH4_OBSIA_CFRM                    INST_OBSIA_CFRM(
   .CLKA                           ( CFRM_CLKA ),
   .WEA                            ( CFRM_WEA ),
   .ADDRA                          ( CFRM_ADDRA[9:0] ),
   .DINA                           ( CFRM_DINA[8:0] ),
   .DOUTA                          ( CFRM_DOUTA[8:0] ),

   .CLKB                           ( CFRM_CLKB ),
   .ADDRB                          ( CFRM_ADDRB[9:0] ),
   .DOUTB                          ( CFRM_DOUTB[8:0] )
   );

  assign CFRD_OUT_FMCNT4[1:0]      = CFRD_RL2_FMCNT4[1:0];
  assign CFRD_OUT_FMCNT270[8:0]    = CFRD_RL2_FMCNT270[8:0];
  assign CFRD_OUT_FMCNT9[3:0]      = CFRD_RL2_FMCNT9[3:0];
  assign CFRD_OUT_DATA[7:0]        = CFRD_RL2_DATA[7:0];
  assign CFRD_OUT_SECTOR[2:0]      = CFRD_RL2_SECTOR[2:0];
  assign CFRD_OUT_CF[7:0]          = CFRM_DOUTB[7:0];
  assign CFRD_OUT_OBSI_EN          = CFRM_DOUTB[8];

always @( posedge SOH4_RESET or posedge SOH4_TCLK ) begin
   if ( SOH4_RESET==1'b1 ) begin
      DTRD_RL1_FMCNT4[1:0]                          <= 2'd0;
      DTRD_RL2_FMCNT4[1:0]                          <= 2'd0;
      DTRD_RL1_FMCNT270[8:0]                        <= 9'd0;
      DTRD_RL2_FMCNT270[8:0]                        <= 9'd0;
      DTRD_RL1_FMCNT9[3:0]                          <= 4'd0;
      DTRD_RL2_FMCNT9[3:0]                          <= 4'd0;
      DTRD_RL1_DATA[7:0]                            <= 8'd0;
      DTRD_RL2_DATA[7:0]                            <= 8'd0;
      DTRD_RL1_OBSI_EN                              <= 1'b0;
      DTRD_RL2_OBSI_EN                              <= 1'b0;
      DTRD_RL1_CF[7:0]                              <= 8'd0;
      DTRD_RL2_CF[7:0]                              <= 8'd0;
   end
   else begin
      DTRD_RL1_FMCNT4[1:0]                          <= CFRD_OUT_FMCNT4;
      DTRD_RL2_FMCNT4[1:0]                          <= DTRD_RL1_FMCNT4[1:0];
      DTRD_RL1_FMCNT270[8:0]                        <= CFRD_OUT_FMCNT270[8:0];
      DTRD_RL2_FMCNT270[8:0]                        <= DTRD_RL1_FMCNT270[8:0];
      DTRD_RL1_FMCNT9[3:0]                          <= CFRD_OUT_FMCNT9[3:0];
      DTRD_RL2_FMCNT9[3:0]                          <= DTRD_RL1_FMCNT9[3:0];
      DTRD_RL1_DATA[7:0]                            <= CFRD_OUT_DATA[7:0];
      DTRD_RL2_DATA[7:0]                            <= DTRD_RL1_DATA[7:0];
      DTRD_RL1_OBSI_EN                              <= CFRD_OUT_OBSI_EN;
      DTRD_RL2_OBSI_EN                              <= DTRD_RL1_OBSI_EN;
      DTRD_RL1_CF[7:0]                              <= CFRD_OUT_CF[7:0];
      DTRD_RL2_CF[7:0]                              <= DTRD_RL1_CF[7:0];
   end
end

  assign DTRD_OUT_FMCNT4[1:0]       = DTRD_RL2_FMCNT4[1:0];
  assign DTRD_OUT_FMCNT270[8:0]     = DTRD_RL2_FMCNT270[8:0];
  assign DTRD_OUT_FMCNT9[3:0]       = DTRD_RL2_FMCNT9[3:0];
  assign DTRD_OUT_DATA[7:0]         = DTRD_RL2_DATA[7:0];
  assign DTRD_OUT_OBSI_EN           = DTRD_RL2_OBSI_EN;
  assign DTRD_OUT_OBSI[7:0]         = DTRM_DOUTB[7:0];
  assign DTRD_OUT_CF[7:0]           = DTRD_RL2_CF[7:0];




// ++++++++++++++++   Insert the overhead bytes into the data stream   ++++++++++++++++++  //
always @( posedge SOH4_RESET or posedge SOH4_TCLK ) begin
   if ( SOH4_RESET==1'b1 ) begin
      OBSIA_OUT_FMCNT4[1:0]                           <= 2'd0;
      OBSIA_OUT_FMCNT270[8:0]                         <= 9'd0;
      OBSIA_OUT_FMCNT9[3:0]                           <= 4'd0;
   end
   else begin
      OBSIA_OUT_FMCNT4[1:0]                           <= DTRD_OUT_FMCNT4[1:0];
      OBSIA_OUT_FMCNT270[8:0]                         <= DTRD_OUT_FMCNT270[8:0];
      OBSIA_OUT_FMCNT9[3:0]                           <= DTRD_OUT_FMCNT9[3:0];
   end
end

always @( posedge SOH4_RESET or posedge SOH4_TCLK ) begin
   if ( SOH4_RESET==1'b1 )
      OBSIA_OUT_DATA[7:0]                             <= 8'd0;
   else begin
      if ( DTRD_OUT_FMCNT9[3:0]==4'd3 )     // the AU point row, no change
         OBSIA_OUT_DATA[7:0]                          <= DTRD_OUT_DATA[7:0];
      else if ( DTRD_OUT_FMCNT270[8:0]<9'd9 ) begin
         if ( DTRD_OUT_FMCNT4[1:0]==2'd0 ) begin
            if ( DTRD_OUT_OBSI_EN==1'b1 )
               OBSIA_OUT_DATA[7:0]                    <= DTRD_OUT_OBSI[7:0];
            else
               OBSIA_OUT_DATA[7:0]                    <= DTRD_OUT_CF[7:0];
         end
         else begin
            OBSIA_OUT_DATA[7:0]                       <= 8'd0;
         end
      end
      else
         OBSIA_OUT_DATA[7:0]                          <= DTRD_OUT_DATA[7:0];
   end
end

endmodule
